package la.iok.hzsvn.lewin.movie.service;

import la.iok.hzsvn.lewin.movie.config.MovieEncodeProperty;
import la.iok.hzsvn.lewin.movie.core.Token;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.core.model.DeviceVo;
import la.iok.hzsvn.lewin.movie.core.model.PlayRecordVo;
import la.iok.hzsvn.lewin.movie.core.model.SimpleOrgUnitVo;
import la.iok.hzsvn.lewin.movie.entity.MovieEncryptCode;
import la.iok.hzsvn.lewin.movie.mapper.MovieEncryptCodeMapper;
import la.iok.hzsvn.lewin.movie.services.MovieServiceInvoker;
import la.iok.hzsvn.lewin.mybatis.service.BaseServiceImpl;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.annotations.Nullable;
import la.iok.hzsvn.share.number.ByteArrayUtils;
import la.iok.hzsvn.share.tools.crypto.AESUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

@Service
@EnableConfigurationProperties(MovieEncodeProperty.class)
public class MovieEncryptCodeServiceImpl extends BaseServiceImpl<MovieEncryptCode, MovieEncryptCodeMapper,Long> implements MovieEncryptCodeService {
    private final MovieServiceInvoker movieServiceInvoker;
    private final MovieEncodeProperty movieEncodeProperty;

    public MovieEncryptCodeServiceImpl(MovieEncryptCodeMapper mapper, MovieServiceInvoker movieServiceInvoker,
                                       MovieEncodeProperty movieEncodeProperty) {
        super(mapper);
        this.movieServiceInvoker = movieServiceInvoker;
        this.movieEncodeProperty = movieEncodeProperty;
    }

    @Nullable
    @Override
    public MovieEncryptCode movieEncryptCode(Long movieId) {
        return select("movieId",movieId);
    }

    @Nullable
    @Override
    public MovieEncryptCode movieEncryptCode(@NotNull Token token, @NotNull Long movieId) {
        if(movieEncodeProperty.validateBeforeGetEncoder()){
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(token.getDeviceId(), "设备","只能由PC服务器调用");
            DeviceVo device = movieServiceInvoker.deviceInfo(token.getDeviceId());
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(device, "设备", "设备不存在");
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(device.getCode(),"设备编码","设备编码不能为空");
            ErrorCode.PROPERTY_CHECK_ERROR.assertTrue(device.getCode().startsWith("PC_"),"设备编码","当前设备不是播放器服务器");
            SimpleOrgUnitVo orgUnit = movieServiceInvoker.orgUnitInfo(device.getOrgUnitId());
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(orgUnit,"店铺","设备所属店铺不存在");
            ErrorCode.PROPERTY_CHECK_ERROR.assertTrue(device.getRoomId() != null && device.getRoomId() > 0,"房间","设备未关联房间");
            //验证当前有没有在进行中的开本记录
            List<PlayRecordVo> list = movieServiceInvoker.roomPlayingRecords(device.getRoomId());
            ErrorCode.PROPERTY_CHECK_ERROR.assertNotNull(list.stream().map(PlayRecordVo::getMovieId).filter(id-> Objects.equals(id,movieId)).findFirst().orElse(null),
                    "剧本","剧本未在当前房间开本");
        }
        return select("movieId",movieId);
    }

    @NotNull
    @Override
    public MovieEncryptCode save(@NotNull Long movieId) {
        MovieEncryptCode code = new MovieEncryptCode();
        code.setMovieId(movieId);
        code.setKeyId(ByteArrayUtils.toHexString(AESUtils.randomAESIV(16)));
        code.setKey(ByteArrayUtils.toHexString(AESUtils.randomAESKey(16)));
        insertSelective(code);
        return code;
    }
}
